class HeapQueue {
    queue = []
    map = null
    constructor(queue, map) {
        this.queue = queue
        this.map = map
    }
    heapify(k) {
        for (let i = Math.floor((k - 1) / 2); i >= 0; i--) {
            this.heapAdjust(i, k - 1)
        }
    }
    heapAdjust(index, end) {
        let left = 2 * index + 1
        let right = left + 1
        while (left <= end) {
            let target = index;
            if (this.map.get(this.queue[left]) < this.map.get(this.queue[target])) {
                target = left
            }
            if (right <= end && this.map.get(this.queue[right]) < this.map.get(this.queue[target])) {
                target = right
            }
            if (target === index) {
                break
            }
            [this.queue[target], this.queue[index]] = [this.queue[index], this.queue[target]];
            index = target
            left = 2 * index + 1
            right = left + 1
        }
    }
    heappop() {
        let size = this.queue.length
        [this.queue[0], this.queue[size - 1]] = [this.queue[size - 1], this.queue[0]];
        let top = this.queue.pop()
        this.heapAdjust(0, size - 2)
        return top
    }
    heappush(val) {
        this.queue.push(val)
        let size = this.queue.length
        let i = size - 1
        while (Math.floor((i - 1) / 2) >= 0) {
            let curRoot = Math.floor((i - 1) / 2)
            if (this.map.get(this.queue[curRoot]) < this.map.get(this.queue[i])) {
                break
            }
            nums[i] = nums[curRoot]
            i = curRoot
        }
    }
}

function topKFrequent(nums, k) {
    let map = new Map
    for (const item of nums) {
        map.set(item, (map.get(item) || 0) + 1)
    }
    let arr = [...new Set(nums)]
    let heapQueue = new HeapQueue(arr, map)
    heapQueue.heapify(k)
    for (let i = k; i < heapQueue.queue.length; i++) {
        if (map.get(heapQueue.queue[i]) > map.get(heapQueue.queue[0])) {
            [heapQueue.queue[i], heapQueue.queue[0]] = [heapQueue.queue[0], heapQueue.queue[i]];
            heapQueue.heapAdjust(0, k - 1)
        }
    }
    return heapQueue.queue.slice(0, k)
}

let nums =
    [5, 1, -1, -8, -7, 8, -5, 0, 1, 10, 8, 0, -4, 3, -1, -1, 4, -5, 4, -3, 0, 2, 2, 2, 4, -2, -4, 8, -7, -7, 2, -8, 0, -8, 10, 8, -8, -2, -9, 4, -7, 6, 6, -1, 4, 2, 8, -3, 5, -9, -3, 6, -8, -5, 5, 10, 2, -5, -1, -5, 1, -3, 7, 0, 8, -2, -3, -1, -5, 4, 7, -9, 0, 2, 10, 4, 4, -4, -1, -1, 6, -8, -9, -1, 9, -9, 3, 5, 1, 6, -1, -2, 4, 2, 4, -6, 4, 4, 5, -5], k = 7
console.log(topKFrequent(nums, k))